﻿using Lr.Templating.FluentMapping;
using Lr.Templating.FluentMapping.Fakes;
using System;
using System.Collections.Generic;
using Xunit;

namespace Lr.Templating.Tests
{
    public class GenericTemplateTests
    {
        [Fact]
        public void TestConstructorWithEmptyString()
        {
            // Arrange
            // Act
            Assert.ThrowsDelegate sut =
            () => {
                var genericTemplate = new GenericTemplate<AppDomain>(String.Empty);
            };

            // Assert
            Assert.Throws<ArgumentNullException>(sut);
        }

        [Fact]
        public void TestTemplateString()
        {
            // Arrange
            var templateString = "template";
            var sut = new GenericTemplate<AppDomain>(templateString);

            // Act
            var result = sut.TemplateString;

            // Assert
            Assert.Equal<string>(templateString, result);
        }

        [Fact]
        public void TestGenericParameter()
        {
            // Arrange
            var sut = new GenericTemplate<AppDomain>("template");

            // Act
            // Assert
            Assert.IsType<GenericTemplate<AppDomain>>(sut);
        }

        [Fact]
        public void TestMapThrowsArgumentNullException()
        {
            // Arrange
            var sut = new GenericTemplate<AppDomain>("template");

            // Act
            Assert.ThrowsDelegate resultEmptyString =
            () => {
                sut.Map(String.Empty);
            };
            Assert.ThrowsDelegate resultWhiteSpaceString =
            () => {
                sut.Map("   ");
            };
            Assert.ThrowsDelegate resultNull =
            () => {
                sut.Map(null);
            };

            // Assert
            Assert.Throws<ArgumentNullException>(resultEmptyString);
            Assert.Throws<ArgumentNullException>(resultWhiteSpaceString);
            Assert.Throws<ArgumentNullException>(resultNull);
        }

        [Fact]
        public void TestMapReturnsCorrectTemplateMappingBuilder()
        {
            // Arrange
            var sut = new GenericTemplate<AppDomain>("template");

            // Act
            var result = sut.Map("placeholder");

            // Assert
            Assert.True(result is IGenericTemplateMappingBuilder<AppDomain>);
        }

        [Fact]
        public void TestMapStoresTemplateMapping()
        {
            // Arrange
            var sut = new GenericTemplate<AppDomain>("template");

            // Act
            sut.Map("placeholder").To("value");

            // Assert
            Assert.Equal<int>(1, ((List<ITemplateMapping>)sut.TemplateMappings).Count);
        }

        [Fact]
        public void TestGetProcessedTemplate()
        {
            // Arrange
            var appDomain = AppDomain.CurrentDomain;
            var appDomainString = appDomain.Id;
            var dateString = DateTime.Now.ToShortDateString();
            var sut = new GenericTemplate<AppDomain>("{date} {appdomain}");

            // Act
            sut.Map("{date}").To(() => DateTime.Now.ToShortDateString());
            sut.Map("{appdomain}").To((x) => x.Id.ToString());
            var result = sut.GetProcessedTemplate(appDomain);
            var expected = String.Format("{0} {1}", dateString, appDomainString);

            // Assert
            Assert.Equal<string>(expected, result);
        }

        [Fact]
        public void TestTemplateMappingsIsCreatedOnConstruction()
        {
            // Arrange
            var sut = new GenericTemplate<AppDomain>("template");

            // Act
            // Assert
            Assert.NotNull(sut.TemplateMappings);
            Assert.Equal<int>(0, ((List<ITemplateMapping>)sut.TemplateMappings).Count);
        }

        [Fact]
        public void TestTemplateMappingsGetStored()
        {
            // Arrange
            var sut = new GenericTemplate<AppDomain>("template");
            var mapping = new StubITemplateMapping();

            // Act
            sut.AddMapping(mapping);

            // Assert
            Assert.Contains<ITemplateMapping>(mapping, sut.TemplateMappings);
            Assert.Equal<int>(1, ((List<ITemplateMapping>)sut.TemplateMappings).Count);
        }
    }
}
